package com.xyt.imei.core.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.luminary.common.framework.core.exception.SysException;
import com.luminary.common.framework.core.model.Pagination;
import com.luminary.common.framework.dao.GenericDao;
import com.luminary.common.framework.service.impl.GenericServiceImpl;
import com.xyt.imei.core.dao.StoreDao;
import com.xyt.imei.core.dao.TaskDao;
import com.xyt.imei.core.dao.TaskDetailDao;
import com.xyt.imei.core.meta.StoreStatusEnum;
import com.xyt.imei.core.meta.TaskDetailStatusEnum;
import com.xyt.imei.core.meta.ValidateConstants;
import com.xyt.imei.core.model.po.Store;
import com.xyt.imei.core.model.po.Task;
import com.xyt.imei.core.model.po.TaskDetail;
import com.xyt.imei.core.service.TaskService;

@Service
public class TaskServiceImpl extends GenericServiceImpl<Task, Integer> implements TaskService {

	public static final int BATCH_SEGMENT_NO = 100;
	
	@Autowired
	private TaskDao taskDao;
	
	@Autowired
	private TaskDetailDao taskDetailDao;
	
	@Autowired
	private StoreDao storeDao;
	
	@Override
	protected GenericDao<Task, Integer> getGenericDao() {
		return this.taskDao;
	}
	
	@Override
	public Pagination<TaskDetail> findSuccessByPage(Pagination<TaskDetail> pagination) throws Exception {
		Map<String,Object> params = pagination.getParams();
        long totalRecords = taskDetailDao.selectRecordCountSuccessByPage(params);
        pagination.setTotalRecords((int) totalRecords);// 分页总记录数
        pagination.setTotalPages(pagination.countTotalPages());// 分页总页数
        pagination.setCurrentPage(pagination.countCurrentPage());// 当前页
        pagination.setStartRow(pagination.countStartRow());// 当前记录起始索引
        params.put(Pagination.START_ROW_NAME, pagination.getStartRow());
        params.put(Pagination.PAGE_SIZE_NAME, pagination.getPageSize());
        List<TaskDetail> results = taskDetailDao.selectSuccessByPage(params);
        pagination.setResults(results);// 分页数据
		return pagination;
	}

	@Override
	public Pagination<TaskDetail> findFailureByPage(Pagination<TaskDetail> pagination) throws Exception {
		Map<String,Object> params = pagination.getParams();
        long totalRecords = taskDetailDao.selectRecordCountFailureByPage(params);
        pagination.setTotalRecords((int) totalRecords);// 分页总记录数
        pagination.setTotalPages(pagination.countTotalPages());// 分页总页数
        pagination.setCurrentPage(pagination.countCurrentPage());// 当前页
        pagination.setStartRow(pagination.countStartRow());// 当前记录起始索引
        params.put(Pagination.START_ROW_NAME, pagination.getStartRow());
        params.put(Pagination.PAGE_SIZE_NAME, pagination.getPageSize());
        List<TaskDetail> results = taskDetailDao.selectFailureByPage(params);
        pagination.setResults(results);// 分页数据
		return pagination;
	}
	
	@Override
	@Transactional
	public boolean addTask(Task task, List<TaskDetail> taskDetailList, int targetId) throws Exception {
		
		List<Store> storeList = validate(task, taskDetailList, targetId);
		return addBatchTaskBySegment(task, taskDetailList, storeList);
		
	}

	private List<Store> validate(Task task, List<TaskDetail> taskDetailList, int targetId) {
		
		if(targetId == task.getCreateBy())
			throw new SysException("500", "不能给自己调拨");
		
		List<Store> storeList = new ArrayList<Store>();
		
		addTask(task);
		
		// 校验
		taskDetailList.forEach(t->{
			String imeiNo = t.getImeiNo();
			t.setTaskId(task.getTaskId());
			if(!imeiNo.matches(ValidateConstants.REGEXP_IMEI)) {
				t.setStatus(TaskDetailStatusEnum.FAILURE.getValue());
				t.setRemark("串号格式不正确");
				t.setCreateBy(task.getCreateBy());
				t.setCreateDate(new Date());
			} 
			else {
				Store store = storeDao.selectByPrimaryKey(imeiNo);
				if(store == null) {
					t.setStatus(TaskDetailStatusEnum.FAILURE.getValue());
					t.setRemark("库存中没有该串号");
					t.setCreateBy(task.getCreateBy());
					t.setCreateDate(new Date());
				} 
				else if(store.getUserId() != task.getCreateBy()) {
					t.setStatus(TaskDetailStatusEnum.FAILURE.getValue());
					t.setRemark("库存中没有该串号");
					t.setCreateBy(task.getCreateBy());
					t.setCreateDate(new Date());
				}
				else if(store.getStatus() == StoreStatusEnum.WAIT_RECIVE.getValue()) {
					t.setStatus(TaskDetailStatusEnum.FAILURE.getValue());
					t.setRemark("该串号已经调拨了");
					t.setCreateBy(task.getCreateBy());
					t.setCreateDate(new Date());
				}
				else {
					t.setStatus(TaskDetailStatusEnum.SUCCESS.getValue());
					t.setCreateBy(task.getCreateBy());
					t.setCreateDate(new Date());
					
					store.setImeiNo(t.getImeiNo());
					store.setTargetUserId(targetId);
					store.setStatus(StoreStatusEnum.WAIT_RECIVE.getValue());
					store.setUpdateBy(task.getCreateBy());
					store.setUpdateDate(new Date());
					storeList.add(store);
				}
			}
		});
		
		return storeList;
		
	}
	
	private boolean addTask(Task task) {
		
		boolean isSuccess = taskDao.insertSelective(task) == 1;
		if(!isSuccess)
			throw new SysException("500", "新增任务失败");
		return isSuccess;
		
	}
	
	private boolean addBatchTaskBySegment(Task task, List<TaskDetail> taskDetailList, List<Store> storeList) throws Exception {
		
		boolean isSuccess = true;
		
		if(taskDetailList.size() < BATCH_SEGMENT_NO) {
			isSuccess = addBatchTaskInDB(taskDetailList, storeList);
			if(!isSuccess)
				throw new SysException("500", "新增任务失败");
		} else {
			int loop = taskDetailList.size() % BATCH_SEGMENT_NO == 0 ? taskDetailList.size()/BATCH_SEGMENT_NO : taskDetailList.size()/BATCH_SEGMENT_NO + 1;
			int i = 0;
			while(i<loop) {
				List<TaskDetail> loopTaskDetailList = taskDetailList.subList(BATCH_SEGMENT_NO*i, BATCH_SEGMENT_NO*(i+1)>taskDetailList.size() ? taskDetailList.size() : BATCH_SEGMENT_NO*(i+1));
				isSuccess = addBatchTaskDetail(loopTaskDetailList);
				if(!isSuccess)
					throw new SysException("500", "新增任务失败");
				i++;
			}
			
			loop = storeList.size() % BATCH_SEGMENT_NO == 0 ? storeList.size()/BATCH_SEGMENT_NO : storeList.size()/BATCH_SEGMENT_NO + 1;
			i = 0;
			while(i<loop) {
				List<Store> loopStoreList = storeList.subList(BATCH_SEGMENT_NO*i, BATCH_SEGMENT_NO*(i+1)>storeList.size() ? storeList.size() : BATCH_SEGMENT_NO*(i+1));
				isSuccess = addBatchStore(loopStoreList);
				if(!isSuccess)
					throw new SysException("500", "修改库存状态失败");
				i++;
			}
		}
		
		return isSuccess;
		
	}
	
	private boolean addBatchTaskInDB(List<TaskDetail> taskDetailList, List<Store> storeList) throws Exception {
		boolean isSuccess = addBatchTaskDetail(taskDetailList);
		if(!isSuccess)
			throw new SysException("500", "新增任务失败");
		
		isSuccess = addBatchStore(storeList);
		if(!isSuccess)
			throw new SysException("500", "修改库存状态失败");
		
		return isSuccess;
	}
	
	private boolean addBatchTaskDetail(List<TaskDetail> taskDetailList) throws Exception {
		boolean isSuccess = taskDetailDao.insertByBatch(taskDetailList) == taskDetailList.size();
		if(!isSuccess)
			throw new SysException("500", "新增任务失败");
		
		return isSuccess;
	}
	
	private boolean addBatchStore(List<Store> storeList) throws Exception {
		boolean isSuccess = true;
		// 可能所有的串号都不符合校验
		if(storeList.size() != 0) {
			// 乐观更新
			isSuccess = storeDao.updateWaitReciveStatusByBatch(storeList) == storeList.size();
			if(!isSuccess)
				throw new SysException("500", "修改库存状态失败，可能其他人正在修改，请稍后重试");
		}
		
		return isSuccess;
	}

}
